<?
define('ROOT', $_SERVER['DOCUMENT_ROOT']);
require_once(ROOT.'/public/global.php');
require_once(ROOT.'/lang/'.$LN.'.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<? require_once(ROOT.'/public/ref.php'); ?>
<title>mac-rpc - 示例</title>
<meta name="description" content="RPC 远程方法调用" />
<meta name="keywords" content="Javascript JQuery Ext Grid ComoBox Tree Tabs Plugin Demo Download" />
<script type="text/javascript">
$(function(){
	function adjust(){
		var de = document.documentElement
			, ch = de.clientHeight, cw = de.clientWidth;
		$('#body').width(cw - 16);
	}
	$(window).resize(adjust);
	adjust();
});
</script>
</head>
<body>
<? require_once(ROOT.'/public/head.php'); ?>
<div id="body">
	<div class="dir">
<? require_once('./dir.php'); ?>
	</div>
	<div class="main">
		<div id="nav">
			<div id="nav_path">
				<a href="<?=$LP?>">Home</a>
				&gt;
				<a href="<?=$LP?>mac/rpc">mac-rpc</a>
				&gt;
				示例
			</div>
			<div id="nav_back">
				<a href="javascript:history.back()"><?=$Msg['back']?></a>
				|
				<a href="<?=$LP?>"><?=$Msg['up']?></a> &nbsp;&nbsp;
			</div>
			<div class="clear"></div>
		</div>
<h1>mac-rpc - 示例</h1>
前往下载&nbsp;<a href="<?=$LP ?>download.html#rpcDemo">RPC应用示例</a>
|
<a href="<?=$LP ?>download.html#jar">依赖JAR包与源码下载</a>
<h2>同步调用</h2>
&nbsp;&nbsp;服务提供者：provide.xml<br/>
<xmp>
	<service ref="demoService" group="demo" name="demo1"
		interface="com.boarsoft.rpc.sample.DemoService" version="1.0.0"
		timeout="3000">
	</service>
</xmp>
&nbsp;&nbsp;服务提供者：DemoServiceImpl.java<br/>
<xmp>
	@Component("demoService")
	public class DemoServiceImpl implements DemoService {
		@Override
		public String helloSC(User u) {
			if (u == null || Util.strIsEmpty(u.getName())) {
				throw new IllegalArgumentException("Invalid parameter");
			}
			return "Hello ".concat(u.getName());
		}
	}
</xmp>
&nbsp;&nbsp;服务消费者：consume.xml<br/>
<xmp>
	<reference id="demoService" group="demo" name="demo1"
		interface="com.boarsoft.rpc.sample.DemoService" version="1.0.0"
		timeout="6000">
	</reference>
</xmp>
&nbsp;&nbsp;服务消费者：Main.java<br/>
<xmp>
	// 从Spring容器中获取，也可以通过@Autowired等注解方式注入
	DemoService ds = (DemoService) ctx.getBean("demoService");
	Object rs = null;
	
	ro = ds.helloSC(new User("Mac_J"));
	log.info("Result = {}", ro);

	try {
		// 此句会抛出来自服务提供者的异常
		ro = ds.helloSC(new User());
		log.info("Result = {}", ro);
	} catch (Exception e) {
		log.error("AC failed", e);
	}
</xmp>
<h2><a name="sc"></a>指定服务提供者</h2>
&nbsp;&nbsp;RpcContext.specify2用于指定服务提供者<br/>
<xmp>
	RpcContext.specify2("127.0.0.1:9101");
	try {
		ro = ds.helloSC(new User("Mac_J"));
		log.info("Result = {}", ro);
	} finally {
		RpcContext.specify2(null);
	}
</xmp>
<h2><a name="ac"></a>异步调用</h2>
&nbsp;&nbsp;异步调用方法的返回类型必须声明为Object，在编写实现时，需要返回真实的结果。但调用方在调用时获得的是一个Future&lt;Object&gt;<br/>
&nbsp;&nbsp;服务消费者：consume.xml<br/>
<xmp>
	<reference id="demoService" group="demo" name="demo1"
		interface="com.boarsoft.rpc.sample.DemoService" version="1.0.0"
		timeout="6000">
		<method name="helloAC" type="AC">
			<arg type="com.boarsoft.rpc.sample.User" />
		</method>
	</reference>
</xmp>
&nbsp;&nbsp;服务消费者：Main.java<br/>
<xmp>
	Future<Object> ft = null;
	ft = (Future<Object>) ds.helloAC(new User("Mac_J"));
	log.info("Do something before get actual result");
	ro = ft.get();
	log.info("Result = {}", ro);

	// 此句不会抛出异常，返回的结果是远程方法内部抛出的异常
	ft = (Future<Object>) ds.helloAC(new User());
	log.info("Do something before get actual result");
	ro = ft.get();
	log.info("Result = {}", ro);
</xmp>
<h2><a name="sb"></a>同步广播方法</h2>
&nbsp;&nbsp;同步广播方法也是是需要特殊处理的方法，其返回值必须是Object类型。<br/>
&nbsp;&nbsp;在编写服务方的实现时，需要返回真实的结果。但在服务的调用方（服务消费者）拿到的对象却时Map&lt;String, Object&gt;类型。此map的key是执行此方法的节点的地址，形如：IP:PORT，而map的value才是实际的结果。
&nbsp;&nbsp;服务消费者：consume.xml<br/>
<xmp>
	<reference id="demoService" group="demo" name="demo1"
		interface="com.boarsoft.rpc.sample.DemoService" version="1.0.0"
		timeout="6000">
		<method name="helloSB" type="SB">
			<arg type="com.boarsoft.rpc.sample.User" />
		</method>
	</reference>
</xmp>
&nbsp;&nbsp;服务消费者：Main.java<br/>
<xmp>
	Map<String, Object> rm = null;
	rm = (Map<String, Object>) ds.helloSB(new User("Mac_J"));
	for (String k : rm.keySet()) {
		ro = rm.get(k);
		log.info("{} = {}", k, ro);
	}

	rm = (Map<String, Object>) ds.helloSB(new User());
	for (String k : rm.keySet()) {
		ro = rm.get(k);
		log.info("{} = {}", k, ro);
	}
</xmp>
<h2><a name="ab"></a>异步广播方法</h2>
&nbsp;&nbsp;异步广播方法与同步广播方法在处理上基本相同。异步广播方法采用Future模式，返回Map&lt;String, Future&lt;Object&gt;&gt;，因此在获取实际结果前不会阻塞当前线程。
&nbsp;&nbsp;服务消费者：consume.xml<br/>
<xmp>
	<reference id="demoService" group="demo" name="demo1"
		interface="com.boarsoft.rpc.sample.DemoService" version="1.0.0"
		timeout="6000">
		<method name="helloAB" type="AB">
			<arg type="com.boarsoft.rpc.sample.User" />
		</method>
	</reference>
</xmp>
&nbsp;&nbsp;服务消费者：Main.java<br/>
<xmp>
	Map<String, Object> rm = null;
	rm = (Map<String, Object>) ds.helloAB(new User("Mac_J"));
	for (String k : rm.keySet()) {
		ro = rm.get(k);
		if (ro != null && ro instanceof Future) {
			ro = ((Future<Object>) ro).get();
		}
		log.info("{} = {}", k, ro);
	}

	rm = (Map<String, Object>) ds.helloAB(new User());
	for (String k : rm.keySet()) {
		ro = rm.get(k);
		if (ro != null && ro instanceof Future) {
			ro = ((Future<Object>) ro).get();
		}
		log.info("{} = {}", k, ro);
	}
</xmp>
	</div>
</div>
<? require_once(ROOT.'/public/foot.html'); ?>
</body>
</html>
<?
$fp = ROOT.$LP.'/mac/rpc/';
output(basename(__FILE__), $fp.'demo.html');
?>